package com.ma4567.remotecontroller.UserManager;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ma4567.remotecontroller.MysqlHelper.TableUserManager;
import com.ma4567.remotecontroller.UserManager.User;
import com.ma4567.remotecontroller.util.Cookie;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class UserManager {
    public List<User> users;
    public List<LoggedUser> loggedUsers;

    public int GetNewUserAccount(){
        for(int i = 0; i < 999999999; i++){
            boolean used = false;
            for(User u: users){
                if(u.Account == i) used = true;
            }
            if(!used){
                return i;
            }
        }
        return -1;
    }

    public UserManager() throws SQLException {
        users = TableUserManager.GetUserList();
        loggedUsers = new ArrayList<LoggedUser>();
    }

    public boolean JudgeCookie(String Cookie){
        for(LoggedUser loggedUser : loggedUsers){
            if(loggedUser.Cookie.equals(Cookie)){
                return true;
            }
        }

        return false;
    }

    //get user
    public User getUserByName(String username) {
        for(User user : users){
            if(user.name.equals(username)){
                return user;
            }
        }
        return null;
    }

    public User getUserByCookie(String cookie) {
        for(LoggedUser u : loggedUsers){
            if(u.Cookie.equals(cookie)){
                return getUserByName(u.name);
            }
        }

        return null;
    }

    public User getUserByAccount(int Account) {
        for(User user : users){
            if(user.Account == Account){
                return user;
            }
        }

        return null;
    }

    public LoggedUser getLoggedUserByCookie(String Cookie){
        for(LoggedUser u : loggedUsers){
            if(u.Cookie.equals(Cookie)){
                return u;
            }
        }

        return null;
    }

    //account verify
    public boolean UserVerify(String AccountOrName, String pwd) throws SQLException {
        try{
            int account = Integer.parseInt(AccountOrName);
            return TableUserManager.JustifyUserByAccount(account, pwd);
        }
        catch(Exception e){
            return TableUserManager.JustifyUserByName(AccountOrName, pwd);
        }
    }

    //return cookie
    public String UserLogin(String AccountOrName, String pwd){
        try{
            int account = Integer.parseInt(AccountOrName);

            //user had logged
            for (LoggedUser loggedUser : loggedUsers) {
                if(loggedUser.account == account){
                    return loggedUser.Cookie;
                }
            }

            //user never logged
            String Cookie = com.ma4567.remotecontroller.util.Cookie.GetCookie(32);
            this.loggedUsers.add(new LoggedUser(account, Cookie, getUserByAccount(account).name));
            return loggedUsers.getLast().Cookie;
        } catch (Exception e) {
            //user had logged
            for (LoggedUser loggedUser : loggedUsers) {
                if(loggedUser.name.equals(AccountOrName)){
                    return loggedUser.Cookie;
                }
            }

            //user never logged
            String Cookie = com.ma4567.remotecontroller.util.Cookie.GetCookie(32);
            this.loggedUsers.add(new LoggedUser(getUserByName(AccountOrName).Account, Cookie, getUserByName(AccountOrName).name));
            return loggedUsers.getLast().Cookie;
        }
    }

    //Get Logged User Permission
    public UserPermission GetUserPermission(String Cookie){
        if(!this.JudgeCookie(Cookie)){
            return null;
        }

        String UserName = "null";

        for(LoggedUser u: this.loggedUsers){
            if(u.Cookie.equals(Cookie)){
                UserName = u.name;
            }
        }

        if(UserName.equals("null")){
            return new UserPermission(false, false, false, false, false);
        }
        else{
            return new UserPermission(getUserByName(UserName));
        }
    }

    //Get single item permission
    //Has checked cookie
    //If cookie error return false
    public boolean GetUserSingleItemPermission(String Cookie, String ItemName){
        User TargetUser = getUserByCookie(Cookie);

        if(TargetUser == null){
            return false;
        }

        return switch (ItemName) {
            case "DownloadFile" -> TargetUser.DownloadFile;
            case "UploadFile" -> TargetUser.UploadFile;
            case "DeleteFile" -> TargetUser.DeleteFile;
            case "RemoteControl" -> TargetUser.RemoteControl;
            case "Root" -> TargetUser.Root;
            default -> false;
        };
    }

    //set logged user current path
    //cookie had been checked
    public void SetLoggedUserCurrentPath(String Cookie, String path){
        for(LoggedUser u : loggedUsers){
            if(u.Cookie.equals(Cookie)){
                u.CurrentPath = path.replace("%5C", "\\");
                break;
            }
        }
    }

    public List<User> GetAllUser(){
        return this.users;
    }

    public String GetUserPreviousPath(String Cookie){
        for(LoggedUser u : loggedUsers){
            if(u.Cookie.equals(Cookie)){
                if(u.CurrentPath.equals("Root")){
                    return "Root";
                }

                if(new File(u.CurrentPath.replace("%5C", "\\")).getParent() == null){
                    return "Root";
                } else {
                    return new File(u.CurrentPath.replace("%5C", "\\")).getParent();
                }
            }
        }
        return "Root";
    }

    public void UpdataUserName(int UserAccount, String NewName) throws SQLException {
        for(User u : users){
            if(u.Account == UserAccount){
                u.name = NewName;
            }
        }

        for(LoggedUser u : loggedUsers){
            if(u.account == UserAccount){
                u.name = NewName;
            }
        }

        TableUserManager.UpdataUserName(UserAccount, NewName);
    }

    public void UpdataUserPassword(int UserAccount, String NewPassword) throws SQLException {
        for(User u : users){
            if(u.Account == UserAccount){
                u.Password = NewPassword;
            }
        }

        TableUserManager.UpdataUserPassword(UserAccount, NewPassword);
    }

    public void UpdataUserPermission(int UserAccount, String PermissionName, boolean permission) throws SQLException {
        for(User u : users){
            if(u.Account == UserAccount){
                switch(PermissionName){
                    case "DownloadFile" -> u.DownloadFile = u.DeleteFile = u.UploadFile = permission;
                    case "RemoteControl" -> u.RemoteControl = permission;
                    case "Root" -> u.Root = permission;
                }
            }
        }
        TableUserManager.UpdateUserPermission(UserAccount, PermissionName, permission);
    }

    public void DeleteUser(int UserAccount) throws SQLException {
        for(LoggedUser u : loggedUsers){
            if(u.account == UserAccount){
                loggedUsers.remove(u);
                break;
            }
        }

        for(User u : users){
            if(u.Account == UserAccount){
                users.remove(u);
                break;
            }
        }
        TableUserManager.DeleteUser(UserAccount);
    }

    public void AddNewUser() throws SQLException {
        TableUserManager.CreateNewUser();
    }
}
